#pragma once
#include "../external/external.h"
#include "Pipeline.h"

namespace Nitro::Renderer {

inline int Pipeline::getUniformLocation(const char* name)
{
    return glGetUniformLocation(id, name);
}

template <>
inline void Pipeline::setUniform(const char* name, const float& value)
{
    glProgramUniform1f(id, getUniformLocation(name), value);
}

template <>
inline void Pipeline::setUniform(const char* name, const glm::vec2& value)
{
    glProgramUniform2fv(id, getUniformLocation(name), 1, glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(const char* name, float x, float y)
{
    glProgramUniform2f(id, getUniformLocation(name), x, y);
}

template <>
inline void Pipeline::setUniform(const char* name, const glm::vec3& value)
{
    glProgramUniform3fv(id, getUniformLocation(name), 1, glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(const char* name, float x, float y, float z)
{
    glProgramUniform3f(id, getUniformLocation(name), x, y, z);
}

template <>
inline void Pipeline::setUniform(const char* name, const glm::vec4& value)
{
    glProgramUniform4fv(id, getUniformLocation(name), 1, glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(const char* name, float x, float y, float z,
                                 float w)
{
    glProgramUniform4f(id, getUniformLocation(name), x, y, z, w);
}

template <>
inline void Pipeline::setUniform(const char* name, const glm::mat2& value)
{
    glProgramUniformMatrix2fv(id, getUniformLocation(name), 1, false,
                              glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(const char* name, const glm::mat3& value)
{
    glProgramUniformMatrix3fv(id, getUniformLocation(name), 1, false,
                              glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(const char* name, const glm::mat4& value)
{
    glProgramUniformMatrix4fv(id, getUniformLocation(name), 1, false,
                              glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(const char* name, const int& value)
{
    glProgramUniform1i(id, getUniformLocation(name), value);
}

template <>
inline void Pipeline::setUniform(int location, const float& value)
{
    glProgramUniform1f(id, location, value);
}

template <>
inline void Pipeline::setUniform(int location, const glm::vec2& value)
{
    glProgramUniform2fv(id, location, 1, glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(int location, float x, float y)
{
    glProgramUniform2f(id, location, x, y);
}

template <>
inline void Pipeline::setUniform(int location, const glm::vec3& value)
{
    glProgramUniform3fv(id, location, 1, glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(int location, float x, float y, float z)
{
    glProgramUniform3f(id, location, x, y, z);
}

template <>
inline void Pipeline::setUniform(int location, const glm::vec4& value)
{
    glProgramUniform4fv(id, location, 1, glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(int location, float x, float y, float z,
                                 float w)
{
    glProgramUniform4f(id, location, x, y, z, w);
}

template <>
inline void Pipeline::setUniform(int location, const glm::mat2& value)
{
    glProgramUniformMatrix2fv(id, location, 1, false, glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(int location, const glm::mat3& value)
{
    glProgramUniformMatrix3fv(id, location, 1, false, glm::value_ptr(value));
}

template <>
inline void Pipeline::setUniform(int location, const glm::mat4& value)
{
    glProgramUniformMatrix4fv(id, location, 1, false, glm::value_ptr(value));
}

} // namespace Nitro::Renderer